From ffc7b2bb0afd04cacbe45cff6f27eb5d644d5b2b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 2 Apr 2018 06:15:50 +0200 Subject: [PATCH] snapshot: Allow passing the bounds of the created paintable This allows being more specific about the size. It's useful in particular when the resulting render nodes might be too small for the size, not only when they are too large. For the latter case, using a clip node would be enough. It also requires adding a clip node when rendering the resulting paintable, but that should be optimized out by GtkSnapshot when not necessary. --- gtk/gtkcolorbutton.c | 2 +- gtk/gtkcolorswatch.c | 2 +- gtk/gtkiconview.c | 2 +- gtk/gtkrendernodepaintable.c | 45 +++++++++++++++-------------- gtk/gtkrendernodepaintableprivate.h | 3 +- gtk/gtksnapshot.c | 18 +++++++++--- gtk/gtksnapshot.h | 6 ++-- gtk/gtktextutil.c | 4 +-- gtk/gtktreeview.c | 2 +- tests/testlist3.c | 2 +- 10 files changed, 51 insertions(+), 35 deletions(-) diff --git a/gtk/gtkcolorbutton.c b/gtk/gtkcolorbutton.c index 9fe9736a1e..d533866434 100644 --- a/gtk/gtkcolorbutton.c +++ b/gtk/gtkcolorbutton.c @@ -330,7 +330,7 @@ set_color_icon (GdkDragContext *context, rgba, &GRAPHENE_RECT_INIT(0, 0, 48, 32), "ColorDragColor"); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); gtk_drag_set_icon_paintable (context, paintable, 0, 0); g_object_unref (paintable); diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c index acd3298f7a..4872f4b667 100644 --- a/gtk/gtkcolorswatch.c +++ b/gtk/gtkcolorswatch.c @@ -175,7 +175,7 @@ drag_set_color_icon (GdkDragContext *context, color, &GRAPHENE_RECT_INIT(0, 0, 48, 32), "ColorDragColor"); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); gtk_drag_set_icon_paintable (context, paintable, 4, 4); g_object_unref (paintable); diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index b9987b294a..cbe65e5a3b 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -6711,7 +6711,7 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, icon_view->priv->item_padding, icon_view->priv->item_padding, FALSE); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); return paintable; } diff --git a/gtk/gtkrendernodepaintable.c b/gtk/gtkrendernodepaintable.c index 18c36a7a8c..5ec8160946 100644 --- a/gtk/gtkrendernodepaintable.c +++ b/gtk/gtkrendernodepaintable.c @@ -28,6 +28,7 @@ struct _GtkRenderNodePaintable GObject parent_instance; GskRenderNode *node; + graphene_rect_t bounds; }; struct _GtkRenderNodePaintableClass @@ -42,29 +43,34 @@ gtk_render_node_paintable_paintable_snapshot (GdkPaintable *paintable, double height) { GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); - graphene_rect_t node_bounds; + gboolean needs_transform; - gsk_render_node_get_bounds (self->node, &node_bounds); + needs_transform = self->bounds.size.width != width || + self->bounds.size.height != height; - if (node_bounds.origin.x + node_bounds.size.width != width || - node_bounds.origin.y + node_bounds.size.height != height) + if (needs_transform) { graphene_matrix_t transform; graphene_matrix_init_scale (&transform, - width / (node_bounds.origin.x + node_bounds.size.width), - height / (node_bounds.origin.y + node_bounds.size.height), + width / (self->bounds.size.width), + height / (self->bounds.size.height), 1.0); gtk_snapshot_push_transform (snapshot, &transform, "RenderNodeScaleToFit"); - gtk_snapshot_append_node (snapshot, self->node); - gtk_snapshot_pop (snapshot); - } - else - { - gtk_snapshot_append_node (snapshot, self->node); } + + gtk_snapshot_push_clip (snapshot, &self->bounds, "RenderNodePaintableClip"); + gtk_snapshot_offset (snapshot, self->bounds.origin.x, self->bounds.origin.y); + + gtk_snapshot_append_node (snapshot, self->node); + + gtk_snapshot_offset (snapshot, -self->bounds.origin.x, -self->bounds.origin.y); + gtk_snapshot_pop (snapshot); + + if (needs_transform) + gtk_snapshot_pop (snapshot); } static GdkPaintableFlags @@ -77,22 +83,16 @@ static int gtk_render_node_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable) { GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); - graphene_rect_t node_bounds; - gsk_render_node_get_bounds (self->node, &node_bounds); - - return node_bounds.origin.x + node_bounds.size.width; + return self->bounds.size.width; } static int gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable) { GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); - graphene_rect_t node_bounds; - - gsk_render_node_get_bounds (self->node, &node_bounds); - return node_bounds.origin.y + node_bounds.size.height; + return self->bounds.size.height; } static void @@ -132,15 +132,18 @@ gtk_render_node_paintable_init (GtkRenderNodePaintable *self) } GdkPaintable * -gtk_render_node_paintable_new (GskRenderNode *node) +gtk_render_node_paintable_new (GskRenderNode *node, + const graphene_rect_t *bounds) { GtkRenderNodePaintable *self; g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL); + g_return_val_if_fail (bounds != NULL, NULL); self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL); self->node = gsk_render_node_ref (node); + self->bounds = *bounds; return GDK_PAINTABLE (self); } diff --git a/gtk/gtkrendernodepaintableprivate.h b/gtk/gtkrendernodepaintableprivate.h index 1eba80ec3f..305eecffb6 100644 --- a/gtk/gtkrendernodepaintableprivate.h +++ b/gtk/gtkrendernodepaintableprivate.h @@ -28,7 +28,8 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GtkRenderNodePaintable, gtk_render_node_paintable, GTK, RENDER_NODE_PAINTABLE, GObject) -GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node); +GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node, + const graphene_rect_t *bounds); G_END_DECLS diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 14514a9689..c383364275 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -277,6 +277,8 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot) /** * gtk_snapshot_free_to_paintable: (skip) * @snapshot: (transfer full): a #GtkSnapshot + * @size: (allow-none): The size of the resulting paintable + * or %NULL to use the bounds of the snapshot * * Returns a paintable for the node that was * constructed by @snapshot and frees @snapshot. @@ -284,11 +286,12 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot) * Returns: (transfer full): a newly-created #GdkPaintable */ GdkPaintable * -gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot) +gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot, + const graphene_size_t *size) { GdkPaintable *result; - result = gtk_snapshot_to_paintable (snapshot); + result = gtk_snapshot_to_paintable (snapshot, size); g_object_unref (snapshot); return result; @@ -1286,6 +1289,8 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot) /** * gtk_snapshot_to_paintable: * @snapshot: a #GtkSnapshot + * @size: (allow-none): The size of the resulting paintable + * or %NULL to use the bounds of the snapshot * * Returns a paintable encapsulating the render node * that was constructed by @snapshot. After calling @@ -1296,13 +1301,18 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot) * Returns: (transfer full): a new #GdkPaintable */ GdkPaintable * -gtk_snapshot_to_paintable (GtkSnapshot *snapshot) +gtk_snapshot_to_paintable (GtkSnapshot *snapshot, + const graphene_size_t *size) { GskRenderNode *node; GdkPaintable *paintable; + graphene_rect_t bounds; node = gtk_snapshot_to_node (snapshot); - paintable = gtk_render_node_paintable_new (node); + gsk_render_node_get_bounds (node, &bounds); + bounds.origin.x = 0; + bounds.origin.y = 0; + paintable = gtk_render_node_paintable_new (node, &bounds); gsk_render_node_unref (node); return paintable; diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index 14cb20470d..7647a6b092 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -58,12 +58,14 @@ GtkSnapshot * gtk_snapshot_new (gboolean GDK_AVAILABLE_IN_ALL GskRenderNode * gtk_snapshot_free_to_node (GtkSnapshot *snapshot); GDK_AVAILABLE_IN_ALL -GdkPaintable * gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot); +GdkPaintable * gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot, + const graphene_size_t *size); GDK_AVAILABLE_IN_ALL GskRenderNode * gtk_snapshot_to_node (GtkSnapshot *snapshot); GDK_AVAILABLE_IN_ALL -GdkPaintable * gtk_snapshot_to_paintable (GtkSnapshot *snapshot); +GdkPaintable * gtk_snapshot_to_paintable (GtkSnapshot *snapshot, + const graphene_size_t *size); GDK_AVAILABLE_IN_ALL gboolean gtk_snapshot_get_record_names (GtkSnapshot *snapshot); diff --git a/gtk/gtktextutil.c b/gtk/gtktextutil.c index 2507da9a84..a636c0ce19 100644 --- a/gtk/gtktextutil.c +++ b/gtk/gtktextutil.c @@ -233,7 +233,7 @@ gtk_text_util_create_drag_icon (GtkWidget *widget, &color); gtk_snapshot_append_layout (snapshot, layout, &color, "TextDragIcon"); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); g_object_unref (layout); return paintable; @@ -343,7 +343,7 @@ gtk_text_util_create_rich_drag_icon (GtkWidget *widget, g_object_unref (layout); g_object_unref (new_buffer); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, &(graphene_size_t) { layout_width, layout_height }); return paintable; } diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 64ddbcc2d9..cbdbb40c3e 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -13944,7 +13944,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, gtk_treeview_snapshot_border (snapshot, &GRAPHENE_RECT_INIT(0, 0, bin_window_width + 2, background_area.height + 2)); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); return paintable; } diff --git a/tests/testlist3.c b/tests/testlist3.c index cfd1bcb6da..cb604057e1 100644 --- a/tests/testlist3.c +++ b/tests/testlist3.c @@ -28,7 +28,7 @@ drag_begin (GtkWidget *widget, gtk_style_context_remove_class (gtk_widget_get_style_context (row), "during-dnd"); cairo_destroy (cr); - paintable = gtk_snapshot_free_to_paintable (snapshot); + paintable = gtk_snapshot_free_to_paintable (snapshot, NULL); gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y); gtk_drag_set_icon_paintable (context, paintable, -x, -y); -- 2.30.2